

public class Prelude extends Object {

    public static Value fst (Value l){
	return (((Pair)l).first());
    }

    public static Value snd (Value l){
	return (((Pair)l).second());
    }

    public static Value head (Value l){
	if (((((Pair)l).second())) instanceof Pair )
	    return(((Pair)(((Pair)l).second())).first());
	else
	    return (((Pair)l).second());
    }

    public static Value tail (Value l){
	if (((((Pair)l).second())) instanceof Pair ){
	    return(new Pair( ((Pair)(((Pair)l).second())).second() ));
	}else
	    return (Prelude.nil());
    }
    
    public static Value cons (Value x,Value l){
      	if (l instanceof Pair)
	    return (new Pair (new Pair (x,((Pair)l).second())));
	else 
	    /* "cons" con la lista vuota */
	    return (new Pair (x));
    }
    
    public static Value cons2 (Value x,Value l){
	    return (new Pair (x,l));
    }
    
    public static Int nil (){
	return (new Int(0));
    }

    public static Bool isNull(Value v){
	return (Prelude.boxBool(v == Prelude.nil()));
    }

    public static Value addInt(Value m,Value n){
	return (new Int(((Int)m).value() + ((Int)n).value()));
    }

    public static Value subInt(Value m,Value n){
	return (new Int(((Int)m).value() - ((Int)n).value()));
    }

    public static Value mulInt(Value m,Value n){
	return (new Int(((Int)m).value() * ((Int)n).value()));
    }

    public static Value divInt(Value m,Value n){
	return (new Int(((Int)m).value() / ((Int)n).value()));
    }

    public static Value modInt(Value m,Value n){
	return (new Int(((Int)m).value() % ((Int)n).value()));
    }

    public static Value negInt(Value m){
	return (new Int(- ((Int)m).value()));
    }

    /*
    public static Value addFloat(Value m,Value n){
	return (new Float(((Float)m).value() + ((Float)n).value()));
    }

    public static Value subFloat(Value m,Value n){
	return (new Float(((Float)m).value() - ((Float)n).value()));
    }

    public static Value mulFloat(Value m,Value n){
	return (new Float(((Float)m).value() * ((Float)n).value()));
    }

    public static Value divFloat(Value m,Value n){
	return (new Float(((Float)m).value() / ((Float)n).value()));
    }

    public static Value modFloat(Value m,Value n){
	return (new Float(((Float)m).value() % ((Float)n).value()));
    }

    public static Value negFloat(Value m){
	return (new Float(- ((Float)m).value()));
    }
    
    public static String stringOfInt (Value n){
	return (new String(((Int)n).toString()));
    }

    public static Value intOfFloat (Value f){
	return (new Int(((Float)f).value()));
    }

    public static Value intOfString (Value s){
	return (new Int(Integer.valueOf(((String)s).value()).intValue()));
    }

    //return [[Int alloc] initWithInt: [[s value] intValue]];


    public static String stringOfFloat (Value n){
	return (new String(((Float)n).toString()));
    }

    public static Value floatOfString (Value s){
	return(new Float(java.lang.Float.valueOf(((String)s).value()).floatValue()));
    }

    public static Value floatOfInt (Value n){
	return (new Float(((Int)n).value()));
    }
    */

    public static Bool andBool(Value b,Value c){
	return (new Bool(((Bool)b).value() && ((Bool)c).value()));
    } 
    
    public static Bool orBool(Value b,Value c){
	return (new Bool(((Bool)b).value() || ((Bool)c).value()));
    }

    public static Bool notBool(Value b){
	return (new Bool(!((Bool)b).value()));
    }
    
    /*
    public static String concatString (String s,String t){
	return (new String(s.value() + t.value()));
    }
    */

    public static Bool boxBool (boolean b){
	return (new Bool(b));
    }

    public static Int boxInt (int n){
	return (new Int(n));
    }
	
    public static Float boxFloat(float f){
	return (new Float(f));
    }

    public static String boxString (java.lang.String s){
	return (new String(s));
    }

    public static Bool eq (Value x,Value y) {
	if (x instanceof Int && y instanceof Int) {
	    return (new Bool(((Int)x).value() == ((Int)y).value()));
	} else
	if (x instanceof Bool && y instanceof Bool) {
	    return (new Bool(((Bool)x).value() == ((Bool)y).value()));
	} else
	return (new Bool(false));
    }

    public static Bool ne (Value x,Value y){
	return (notBool(eq(x, y)));
    }

    public static Bool le (Value x,Value y){
	if (x instanceof Int && y instanceof Int) {
	    return (new Bool(((Int)x).value() <= ((Int)y).value()));
	} else
	    return null;
    }

    public static Bool lt (Value x,Value y){
	if (x instanceof Int && y instanceof Int) {
	    return (new Bool(((Int)x).value() < ((Int)y).value()));
	} else
	    return null;
    }

    public static Bool ge (Value x,Value y){
	return (le(y, x));
    }

    public static Bool gt (Value x,Value y){
	return (lt(y, x));
    }
}
